﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Algobox.JuicyLib.SQL.LiquidView;
using System.Data.Linq;
using System.Net;

namespace Algobox.JuicyLib.Apps.Sterling
{
    public class SterlingFileDrop : IDisposable
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileDate">File date to generate the files for</param>
        /// <param name="ftplocation">URI inclusing the directory of where to save the files</param>
        /// <param name="user">FTP username</param>
        /// <param name="pass">FTP password</param>
        public SterlingFileDrop(List<string> symbolsGBP)
        {
            _symbolsGBP = symbolsGBP;
            m_Linq = new Algobox.JuicyLib.SQL.LiquidView.LiquidViewLinqDataContext();
        }

        public SterlingFileDrop(List<string> symbolsGBP, string dbConnection)
        {
            _symbolsGBP = symbolsGBP;
            m_Linq = new Algobox.JuicyLib.SQL.LiquidView.LiquidViewLinqDataContext(dbConnection);
        }

        const string PROCESSNAME = "FTPFileDrop";

        Algobox.JuicyLib.SQL.LiquidView.LiquidViewLinqDataContext m_Linq;
        List<string> _symbolsGBP;

        public void Dispose()
        {
            m_Linq.Dispose();
        }


        public void RunPositionFileDrop(DateTime fileDate, string destinationURI, string username, string password)
        {
            string positions = String.Empty;
            try
            {
                positions = GetPositions(fileDate);
            }
            catch (Exception e)
            {
                Console.WriteLine("Position file failed to be generated\r\n" + e);
                m_Linq.ExceptionHandlerThrow(PROCESSNAME, "Failed to load STI Positions from database", null);
                return;
            }

            string filename = String.Empty;

            using (WebClient client = new WebClient())
            {
                client.Credentials = new NetworkCredential(username, password);

                try
                {
                    if (positions != String.Empty)
                    {
                        if (fileDate.DayOfWeek == DayOfWeek.Saturday)
                            fileDate = fileDate.AddDays(-1);
                        else if (fileDate.DayOfWeek == DayOfWeek.Sunday)
                            fileDate = fileDate.AddDays(-2);

                        filename = destinationURI.ToString() + "Positions-" + fileDate.ToString("yyyyMMdd") + ".csv";
                        Console.WriteLine("Writing Positions to " + filename);
                        client.UploadData(filename, System.Text.Encoding.ASCII.GetBytes(positions));
                        m_Linq.LogGeneral(PROCESSNAME, "RunPositionFileDrop", "Success", "Wrote positions to " + filename, null, null, null, null, null, null);                    
                    }
                    else
                    {
                        Console.WriteLine("Writing empty positions file to " + filename);
                        client.UploadData(filename, System.Text.Encoding.ASCII.GetBytes(""));
                        m_Linq.ExceptionHandlerThrow(PROCESSNAME, "No positions so sending STI an empty file", null);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to upload file ({0}) to STI\r\n" + e, filename);
                    m_Linq.ExceptionHandlerThrow(PROCESSNAME, "Failed to upload Net Liqs file (" + filename + ") to STI - " + e, null);
                }
            }
        }


        private string GetPositions(DateTime snapshotDate)
        {
            string symbol;
            StringBuilder output = new StringBuilder();
            foreach (var data in m_Linq.GetDataViewSnapshotDailyStockOpenPositions(snapshotDate))
            {
                if (data.SterlingTrader != null && data.SterlingTrader != String.Empty)
                    symbol = data.SterlingTrader;
                else
                    symbol = data.Symbol;
                
                // convert GBP to GBX for UK stocks
                if (data.StockCurrency == "GBP" && !_symbolsGBP.Contains(symbol))
                    data.CurrentSettlement = data.CurrentSettlement * 100;

                output.AppendFormat("{0},{1},{2},{3},{4},E,,,,\r\n",
                    data.AccountId,
                    symbol,
                    data.CurrentPosition > 0 ? "B" : "S",
                    data.CurrentPosition,
                    data.CurrentSettlement);
            }
            foreach (var data in m_Linq.GetDataViewSnapshotDailyOptionsOpenPositions(snapshotDate))
            {
                symbol =
                    data.UnderlyingSymbol.Trim()
                    + ' '
                    + data.ExpiryDate.ToString("yyMMdd")
                    + data.PutCall
                    + (int)(data.Strike * 1000);

                output.AppendFormat("{0},{1},{2},{3},{4},O,{5},{6:yyMMdd},{7},{8}\r\n",
                    data.AccountId,
                    symbol,
                    data.CurrentPosition > 0 ? "B" : "S",
                    Math.Abs(data.CurrentPosition),
                    data.CurrentSettlement,
                    data.UnderlyingSymbol.Trim(),
                    data.ExpiryDate,
                    data.Strike,
                    data.PutCall);
            }
            return output.ToString();
        }
        

        public void RunNetLiqFileDrop(DateTime fileDate, string destinationURI, string username, string password)
        {            
            string positions = String.Empty;
            try
            {
                positions = GetNetLiqs(fileDate);
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed to load Net Liquidities from database\r\n" + e);
                m_Linq.ExceptionHandlerThrow(PROCESSNAME, "Failed to load Net Liquidities from database", null);
                return;
            }

            string filename = String.Empty;

            using (WebClient client = new WebClient())
            {
                client.Credentials = new NetworkCredential(username, password);

                try
                {
                    if (positions != String.Empty)
                    {
                        if (fileDate.DayOfWeek == DayOfWeek.Saturday)
                            fileDate = fileDate.AddDays(-1);
                        else if (fileDate.DayOfWeek == DayOfWeek.Sunday)
                            fileDate = fileDate.AddDays(-2);

                        filename = destinationURI.ToString() + "NetLiq-" + fileDate.ToString("yyyyMMdd") + ".csv";
                        Console.WriteLine("Writing NetLiqs to " + filename);
                        client.UploadData(filename, System.Text.Encoding.ASCII.GetBytes(positions));
                        m_Linq.LogGeneral(PROCESSNAME, "RunNetLiqFileDrop", "Success", "Wrote Net Liqs to " + filename, null, null, null, null, null, null);
                    }
                    else
                    {
                        Console.WriteLine("Writing empty NetLiqs file to " + filename);
                        client.UploadData(filename, System.Text.Encoding.ASCII.GetBytes(""));
                        m_Linq.ExceptionHandlerThrow(PROCESSNAME, "No Net Liqs so sending STI an empty file", null);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Failed to upload file ({0}) to STI\r\n" + e, filename);
                    m_Linq.ExceptionHandlerThrow(PROCESSNAME, "Failed to upload Net Liqs file ("+ filename +") to STI - " + e, null);
                }
            }
        }


        private string GetNetLiqs(DateTime snapshotDate)
        {
            StringBuilder output = new StringBuilder();
            foreach (var data in m_Linq.GetDataViewSnapshotDailyNetLiquidity(snapshotDate))
            {
                output.AppendFormat("{0},{1},{2}\r\n",
                    data.AccountId,
                    data.NetLiq,
                    data.Currency);
            }
            return output.ToString();
        }
    }
}
